package logic_basics

import (
	"APT/internal/consts"
	"APT/internal/dao"
	"APT/internal/library/hgorm/handler"
	hook2 "APT/internal/library/hgorm/hook"
	"APT/internal/model/entity"
	"APT/internal/model/input/input_basics"
	"APT/internal/model/input/input_form"
	"APT/internal/model/input/input_hotel"
	"APT/internal/model/input/input_language"
	"APT/internal/service"
	"context"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/guid"
	"strings"
	"time"

	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
)

type sBasicsCouponType struct{}

func NewBasicsCouponType() *sBasicsCouponType {
	return &sBasicsCouponType{}
}

func init() {
	service.RegisterBasicsCouponType(NewBasicsCouponType())
}

func (s *sBasicsCouponType) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
	return handler.Model(dao.PmsCouponType.Ctx(ctx), option...)
}

func (s *sBasicsCouponType) List(ctx context.Context, in *input_basics.PmsCouponTypeListInp) (list []*input_basics.PmsCouponTypeListModel, totalCount int, err error) {
	mod := s.Model(ctx).Hook(hook2.PmsFindLanguageValueHook)

	mod = mod.Fields(input_basics.PmsCouponTypeListModel{})

	if !g.IsEmpty(in.Type) {
		mod = mod.WhereLike(dao.PmsCouponType.Columns().Type, in.Type)
	}

	if !g.IsEmpty(in.CouponName) {
		mod = mod.WhereLike(dao.PmsCouponType.Columns().CouponName, "%"+in.CouponName+"%")
	}

	if in.ValidityType > 0 {
		mod = mod.Where(dao.PmsCouponType.Columns().ValidityType, in.ValidityType)
	}

	if in.Status > 0 {
		mod = mod.Where(dao.PmsCouponType.Columns().Status, in.Status)
	}

	if !g.IsEmpty(in.Scene) {
		mod = mod.Where(dao.PmsCouponType.Columns().Scene, in.Scene)
	}

	mod = mod.Page(in.Page, in.PerPage)

	mod = mod.OrderAsc(dao.PmsCouponType.Columns().Sort).OrderDesc(dao.PmsCouponType.Columns().Id)

	if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
		err = gerror.Wrap(err, "获取优惠券列表失败，请稍后重试！")
		return
	}
	return
}

func (s *sBasicsCouponType) All(ctx context.Context, in *input_basics.PmsCouponTypeListInp) (list []*input_basics.PmsCouponTypeAllListModel, err error) {
	mod := s.Model(ctx).Hook(hook2.PmsFindLanguageValueHook)

	mod = mod.Fields(input_basics.PmsCouponTypeAllListModel{})

	mod = mod.Where(dao.PmsCouponType.Columns().Status, 1)

	if !g.IsEmpty(in.CouponIds) {
		mod = mod.WhereIn(dao.PmsCouponType.Columns().Id, strings.Split(in.CouponIds, ","))
	}

	mod = mod.OrderDesc(dao.PmsCouponType.Columns().Id)

	if err = mod.Scan(&list); err != nil {
		err = gerror.Wrap(err, "获取优惠券列表失败，请稍后重试！")
		return
	}

	var (
		couponTypeList []*input_basics.PmsCouponTypeAllListModel
	)

	if !g.IsEmpty(in.CouponIds) {
		couponIdArr := strings.Split(in.CouponIds, ",")
		for _, couponId := range couponIdArr {
			for _, v := range list {
				if v.Id == gvar.New(couponId).Int() {
					couponTypeList = append(couponTypeList, v)
				}
			}
		}
		list = couponTypeList
	}

	return
}

func (s *sBasicsCouponType) Edit(ctx context.Context, in *input_basics.PmsCouponTypeEditInp) (err error) {
	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {

		var (
			Object               gdb.Record
			PmsCouponTypeDao     *input_language.LoadLanguage
			PmsCouponTypeDescDao *input_language.LoadLanguage
			LanguageStruct       input_language.LanguageModel
			DescStruct           input_language.LanguageModel
		)
		Uuid := guid.S([]byte("coupon_name"))

		DescUuid := guid.S([]byte("desc"))

		if in.ValidityType == 1 {
			// 当日的23点59分59秒
			in.EndUseTime = gtime.New(gtime.New(in.EndUseTime).StartOfDay()).Add(time.Duration(23) * time.Hour).Add(time.Duration(59) * time.Minute).Add(time.Duration(59) * time.Second)
		}

		if in.Id > 0 {

			if Object, err = dao.PmsCouponType.Ctx(ctx).Where(dao.PmsCouponType.Columns().Id, in.Id).One(); err != nil {
				return
			}

			if !g.IsEmpty(Object["coupon_name"]) {
				Uuid = Object["coupon_name"].String()
				DescUuid = Object["desc"].String()
			}

			PmsCouponTypeDao = &input_language.LoadLanguage{
				Uuid: Uuid,
				Tag:  dao.PmsCouponType.Table(),
				Type: "table",
				Key:  gstr.CaseSnakeFirstUpper("CouponName"),
			}
			LanguageStruct = in.NameLanguage
			if err = service.BasicsLanguage().Sync(ctx, LanguageStruct, PmsCouponTypeDao); err != nil {
				return
			}

			PmsCouponTypeDescDao = &input_language.LoadLanguage{
				Uuid: DescUuid,
				Tag:  dao.PmsCouponType.Table(),
				Type: "table",
				Key:  gstr.CaseSnakeFirstUpper("Desc"),
			}
			DescStruct = in.DescLanguage
			if err = service.BasicsLanguage().Sync(ctx, DescStruct, PmsCouponTypeDescDao); err != nil {
				return
			}

			in.Desc = DescUuid
			in.CouponName = Uuid
			if _, err = s.Model(ctx).
				Fields(input_basics.PmsCouponTypeUpdateFields{}).
				WherePri(in.Id).Data(in).Update(); err != nil {
				err = gerror.Wrap(err, "修改优惠券失败，请稍后重试！")
			}
			return
		}

		var (
			lastInsertId int64
		)
		in.CouponName = Uuid
		in.Desc = DescUuid
		if lastInsertId, err = s.Model(ctx, &handler.Option{FilterAuth: false}).
			Fields(input_basics.PmsCouponTypeInsertFields{}).
			Data(in).OmitEmptyData().InsertAndGetId(); err != nil {
			err = gerror.Wrap(err, "新增优惠券失败，请稍后重试！")
		}

		if lastInsertId < 1 {
			err = gerror.Wrap(err, "新增优惠券失败，请稍后重试！")
			return
		}

		PmsCouponTypeDao = &input_language.LoadLanguage{
			Uuid: Uuid,
			Tag:  dao.PmsCouponType.Table(),
			Type: "table",
			Key:  gstr.CaseSnakeFirstUpper("CouponName"),
		}
		LanguageStruct = in.NameLanguage
		if err = service.BasicsLanguage().Sync(ctx, LanguageStruct, PmsCouponTypeDao); err != nil {
			return
		}

		PmsCouponTypeDescDao = &input_language.LoadLanguage{
			Uuid: DescUuid,
			Tag:  dao.PmsCouponType.Table(),
			Type: "table",
			Key:  gstr.CaseSnakeFirstUpper("Desc"),
		}
		DescStruct = in.DescLanguage
		if err = service.BasicsLanguage().Sync(ctx, DescStruct, PmsCouponTypeDescDao); err != nil {
			return
		}
		return
	})
}

func (s *sBasicsCouponType) Delete(ctx context.Context, in *input_basics.PmsCouponTypeDeleteInp) (err error) {

	if _, err = s.Model(ctx).WherePri(in.Id).Delete(); err != nil {
		err = gerror.Wrap(err, "删除优惠券失败，请稍后重试！")
		return
	}
	return
}

func (s *sBasicsCouponType) MaxSort(ctx context.Context, in *input_basics.PmsCouponTypeMaxSortInp) (res *input_basics.PmsCouponTypeMaxSortModel, err error) {
	if err = dao.PmsCouponType.Ctx(ctx).Fields(dao.PmsCouponType.Columns().Sort).OrderDesc(dao.PmsCouponType.Columns().Sort).Scan(&res); err != nil {
		err = gerror.Wrap(err, "获取优惠券最大排序，请稍后重试！")
		return
	}

	if res == nil {
		res = new(input_basics.PmsCouponTypeMaxSortModel)
	}

	res.Sort = input_form.DefaultMaxSort(res.Sort)
	return
}

func (s *sBasicsCouponType) View(ctx context.Context, in *input_basics.PmsCouponTypeViewInp) (res *input_basics.PmsCouponTypeViewModel, err error) {
	if err = s.Model(ctx).WithAll().WherePri(in.Id).Scan(&res); err != nil {
		err = gerror.Wrap(err, "获取优惠券信息，请稍后重试！")
		return
	}

	if res.Scene == 1 {
		res.PropertyNames = "全部物业可用"
		if !g.IsEmpty(res.PropertyIds) {
			res.PropertyNames = ""
			var propertyArr []*input_hotel.PmsPropertyAllModel
			propertyArr, err = service.HotelService().PropertyAll(ctx, &input_hotel.PmsPropertyAllInp{
				Ids: res.PropertyIds,
			})
			if err != nil {
				err = gerror.Wrap(err, "获取物业失败！")
				return
			}
			if err = gvar.New(propertyArr).Struct(&res.Property); err != nil {
				return
			}
			// 获取物业名称以逗号 分隔
			for _, property := range propertyArr {
				res.PropertyNames = res.PropertyNames + property.Name + "，"
			}
			res.PropertyNames = gstr.TrimRight(res.PropertyNames, "，")
		}
	}

	if res.Scene == 2 {
		res.RestaurantNames = "全部门店可用"
		if !g.IsEmpty(res.RestaurantIds) {
			res.RestaurantNames = ""
			restaurantArr, _ := dao.FoodRestaurant.Ctx(ctx).Hook(hook2.PmsFindLanguageValueHook).Fields("name").
				WhereIn(dao.FoodRestaurant.Columns().Id, strings.Split(res.RestaurantIds, ",")).Array()

			if !g.IsEmpty(restaurantArr) {
				// 获取餐厅名称以逗号 分隔
				for _, restaurant := range restaurantArr {
					res.RestaurantNames = res.RestaurantNames + g.NewVar(restaurant).String() + "，"
				}
				res.RestaurantNames = gstr.TrimRight(res.RestaurantNames, "，")
			}
		}
	}

	if res.Scene == 3 {
		spaServiceTypeStr := "到店/上门"
		if !g.IsEmpty(res.ServiceIds) {
			spaServiceTypeStr = ""
			serviceIdsArr := strings.Split(res.ServiceIds, ",")
			for _, serviceType := range serviceIdsArr {
				switch serviceType {
				case "ToStore":
					spaServiceTypeStr = spaServiceTypeStr + "到店/"
					break
				case "ToDoor":
					spaServiceTypeStr = spaServiceTypeStr + "上门/"
					break
				}

			}
			spaServiceTypeStr = gstr.TrimRight(spaServiceTypeStr, "/")
		}
		res.SpaServiceTypeStr = spaServiceTypeStr
	}

	if res.Scene == 4 {
		carServiceTypeStr := "接机/送机/包车"
		if !g.IsEmpty(res.CarServiceTypes) {
			carServiceTypeStr = ""
			serviceTypeArr := strings.Split(res.CarServiceTypes, ",")
			for _, serviceType := range serviceTypeArr {
				switch serviceType {
				case "PICKUP":
					carServiceTypeStr = carServiceTypeStr + "接机/"
					break
				case "DELIVERY":
					carServiceTypeStr = carServiceTypeStr + "送机/"
					break
				case "CHARTERED":
					carServiceTypeStr = carServiceTypeStr + "包车/"
					break
				}
			}
			carServiceTypeStr = gstr.TrimRight(carServiceTypeStr, "/")
		}
		res.CarServiceTypeStr = carServiceTypeStr
	}

	return
}

func (s *sBasicsCouponType) Status(ctx context.Context, in *input_basics.PmsCouponTypeStatusInp) (err error) {
	if _, err = s.Model(ctx).WherePri(in.Id).Data(g.Map{
		dao.PmsCouponType.Columns().Status: in.Status,
	}).Update(); err != nil {
		err = gerror.Wrap(err, "更新优惠券状态失败，请稍后重试！")
		return
	}
	return
}

func (s *sBasicsCouponType) SendMemberCoupon(ctx context.Context, in *input_basics.PmsSendMemberCouponInp, source int) (err error) {

	return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
		if in.CouponTypeId > 0 {

			var couponType *entity.PmsCouponType
			if err = s.Model(ctx).Where(dao.PmsCouponType.Columns().Id, in.CouponTypeId).Scan(&couponType); err != nil {
				err = gerror.Wrap(err, consts.ErrorORM)
				return
			}

			if g.IsEmpty(couponType) {
				err = gerror.New("优惠券不存在")
				return
			}

			if couponType.Status != 1 {
				err = gerror.New("该优惠券已关闭，无法发放")
				return
			}

			if couponType.Count <= couponType.LeadCount && couponType.Count > 0 {
				err = gerror.New("该优惠券已达领取上限，无法发放")
				return
			}

			var endTime *gtime.Time

			if couponType.ValidityType == 1 {
				endTime = couponType.EndUseTime
			} else if couponType.ValidityType == 2 {
				todayStart := gtime.Now()
				endTime = gtime.New(todayStart).Add(time.Duration(24*couponType.FixedTerm) * time.Hour)
				endTime = gtime.New(endTime.StartOfDay()).Add(time.Duration(23) * time.Hour).Add(time.Duration(59) * time.Minute).Add(time.Duration(59) * time.Second)
			}

			if _, err = g.Model(dao.PmsCoupon.Table()).Ctx(ctx).Safe().
				Fields(input_basics.PmsCouponInsertFields{}).
				Data(g.MapStrAny{
					dao.PmsCoupon.Columns().Type:            couponType.Type,
					dao.PmsCoupon.Columns().CouponName:      couponType.CouponName,
					dao.PmsCoupon.Columns().CouponTypeId:    couponType.Id,
					dao.PmsCoupon.Columns().MemberId:        in.MemberId,
					dao.PmsCoupon.Columns().Scene:           couponType.Scene,
					dao.PmsCoupon.Columns().PropertyIds:     couponType.PropertyIds,
					dao.PmsCoupon.Columns().RestaurantIds:   couponType.RestaurantIds,
					dao.PmsCoupon.Columns().ServiceIds:      couponType.ServiceIds,
					dao.PmsCoupon.Columns().CarServiceTypes: couponType.CarServiceTypes,
					dao.PmsCoupon.Columns().AtLeast:         couponType.AtLeast,

					dao.PmsCoupon.Columns().Money:         couponType.Money,
					dao.PmsCoupon.Columns().Discount:      couponType.Discount,
					dao.PmsCoupon.Columns().DiscountLimit: couponType.DiscountLimit,
					dao.PmsCoupon.Columns().State:         1,
					dao.PmsCoupon.Columns().FetchTime:     gtime.Now().Format("Y-m-d H:i:s"),
					dao.PmsCoupon.Columns().StartTime:     gtime.Now().Format("Y-m-d H:i:s"),
					dao.PmsCoupon.Columns().EndTime:       endTime,
					dao.PmsCoupon.Columns().Source:        source,
				}).OmitEmptyData().InsertAndGetId(); err != nil {
				err = gerror.Wrap(err, "发放优惠券失败，请稍后重试！")
			}

			if _, err = s.Model(ctx).WherePri(in.CouponTypeId).Increment(dao.PmsCouponType.Columns().LeadCount, 1); err != nil {
				err = gerror.Wrap(err, "操作失败，请稍后重试！")
				return
			}
			return
		}

		err = gerror.Wrap(err, "优惠券不存在，请稍后重试！")
		return
	})
}
